package com.xhwl.centiotdata.suppliersystem.dahua;

import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xhwl.centiotdata.pojo.constant.DaHuaConstant;
import com.xhwl.centiotdata.pojo.constant.StrConstant;
import com.xhwl.centiotdata.pojo.dto.dahua.SecurityDaHuaDTO;
import com.xhwl.centiotdata.utils.RedisUtils;
import com.xhwl.common.exception.ApplicationException;
import com.xhwl.common.exception.BusinessException;
import com.xhwl.common.utils.RSAUtils;
import com.xhwl.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author： lianghz
 * @Description：
 * @Date 2021/09/03/ 10:15
 */
@Service
public class GeneralDaHuaHandler {
    private static final Logger log = LoggerFactory.getLogger(GeneralDaHuaHandler.class);

    @Autowired
    private RedisUtils redisUtils;

    public SecurityDaHuaDTO getToken(Integer projectId, Integer productId, String ipAndPort, String loginName, String password) {
        ReentrantLock lock = new ReentrantLock();
        SecurityDaHuaDTO securityDaHuaDTO = null;
        lock.lock();
        try {
            String key = new StringBuffer(StrConstant.SUPPLIER_SYSTEM_TOKEN).append("-").append(projectId).append("-").append(productId).toString();
            Object value = redisUtils.get(key);
            if (value == null) {
                String loginPass = this.getPublicKey(ipAndPort, loginName, password);
                securityDaHuaDTO = this.login(ipAndPort, loginName, loginPass);
                redisUtils.setWithMinute(key, JSONObject.toJSONString(securityDaHuaDTO), 29);
            } else {
                securityDaHuaDTO = JSON.parseObject((String) value, SecurityDaHuaDTO.class);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return securityDaHuaDTO;
    }

    private String getPublicKey(String ipAndPort, String loginName, String passWord) {
        HashMap<String, Object> params = new HashMap<>(1);
        params.put("loginName", loginName);
        JSONObject resultObject = this.post(ipAndPort + DaHuaConstant.PUBLIC_KEY_URL, params);
        if ("false".equals(resultObject.getString("success"))) {
            log.error("【DaHua getPublicKey】path:{};params:{};errMsg:{}", DaHuaConstant.PUBLIC_KEY_URL, JSON.toJSONString(params), resultObject.getString("errMsg"));
            throw new BusinessException("Dahua getPublicKey failed!");
        }
        String loginPass = RSAUtils.encrypt(passWord, resultObject.getString("publicKey"));
        return loginPass;
    }

    private SecurityDaHuaDTO login(String ipAndPort, String loginName, String loginPass) {
        HashMap<String, Object> params = new HashMap<>(2);
        params.put("loginName", loginName);
        params.put("loginPass", loginPass);
        JSONObject resultObject = this.post(ipAndPort + DaHuaConstant.LOGIN_URL, params);
        if ("false".equals(resultObject.getString("success"))) {
            log.error("【DaHua login】path:{};params:{};errMsg:{}", DaHuaConstant.LOGIN_URL, JSON.toJSONString(params), resultObject.getString("errMsg"));
            throw new BusinessException("Dahua login failed!");
        }
        SecurityDaHuaDTO securityDaHuaDTO = SecurityDaHuaDTO.builder()
                .userId(resultObject.getString("id"))
                .userName(loginName)
                .token(resultObject.getString("token")).build();
        return securityDaHuaDTO;
    }

    private JSONObject post(String path, Map<String, Object> params) {
        log.info("【DaHua post】path:{};params:{}", path, JSON.toJSONString(params));
        String result = null;
        try {
            result = HttpRequest
                    .post(path)
                    .body(JSON.toJSONString(params))
                    .execute()
                    .body();
        } catch (HttpException e) {
            log.error("【DaHua post】path:{};params:{}; request failed!", path, JSON.toJSONString(params));
            e.printStackTrace();
            throw new ApplicationException();
        }
        if (StringUtils.isEmpty(result)) {
            log.error("【DaHua post】path:{};params:{};result is null!", path, JSON.toJSONString(params));
            throw new BusinessException();
        }
        log.info("【DaHua post】path:{};params:{};result:{}", path, JSON.toJSONString(params), result);
        return JSON.parseObject(result);
    }

    public JSONObject post(String api, Map<String, Object> params, Integer projectId, Integer productId, String ipAndPort, String loginName, String password) {
        SecurityDaHuaDTO securityDaHuaDTO = this.getToken(projectId, productId, ipAndPort, loginName, password);
        if (securityDaHuaDTO == null) {
            log.error("【DaHua post】path:{};getToken fail!", api);
            return null;
        }
        StringBuffer pathBuffer = new StringBuffer()
                .append(ipAndPort)
                .append(api)
                .append("?userId=")
                .append(securityDaHuaDTO.getUserId())
                .append("&userName=")
                .append(securityDaHuaDTO.getUserName())
                .append("&token=")
                .append(securityDaHuaDTO.getToken());
        return this.post(pathBuffer.toString(), params);
    }

    private JSONObject get(String path) {
        String result = null;
        try {
            result = HttpRequest
                    .get(path)
                    .execute()
                    .body();
        } catch (HttpException e) {
            log.error("【DaHua get】path:{}; request failed!", path);
            e.printStackTrace();
            throw new ApplicationException();
        }
        if (StringUtils.isEmpty(result)) {
            log.error("【DaHua get】path:{};result is null!", path);
            throw new BusinessException();
        }
        log.info("【DaHua get】path:{};result:{}", path, result);
        return JSON.parseObject(result);
    }

    public JSONObject get(String api, Map<String, Object> params, Integer projectId, Integer productId, String ipAndPort, String loginName, String password) {
        SecurityDaHuaDTO securityDaHuaDTO = this.getToken(projectId, productId, ipAndPort, loginName, password);
        if (securityDaHuaDTO == null) {
            log.error("【DaHua post】path:{};getToken fail!", api);
            return null;
        }
        StringBuffer pathBuffer = new StringBuffer()
                .append(ipAndPort)
                .append(api)
                .append("?userId=")
                .append(securityDaHuaDTO.getUserId())
                .append("&userName=")
                .append(securityDaHuaDTO.getUserName())
                .append("&token=")
                .append(securityDaHuaDTO.getToken());
        return this.get(pathBuffer.toString());
    }

    public static String generateOpenCode(Integer accountId,Integer projectId){
        return accountId+"by"+projectId;
    }

}
